#!/usr/bin/env perl
#
# bigButtonDaemon.pl -- a daemon that polls a BigButton looking for triggers
# ------------------
#
# Meant to be used with a board running the BigButton.pde Arduino sketch
#
# Important options:
# -p <portname>  -- serial port of BigButton device
# -l <secs>      -- number of seconds for this daemon to live
# -m <mins>      -- number of mins a button press is good for
# -v             -- verbose, more gives more verbosity
#
#
# An example crontab entry for bigButtonServer might be:
#
# # run every 5 minutes always, verbosely, with 15 minute button 
# */5 * * * * bigbuttonDaemon.pl -v -l 295 -m 15 -p /dev/ttyUSB0 >> $HOME/bigButton.out 2>&1
#
#
# 2010, Tod E. Kurt, http://todbot.com/blog/
#
#

use strict;
use warnings;

use Device::SerialPort;
use Getopt::Long;
use Time::HiRes qw(sleep time);
use LWP::Simple;
 

my $update_url_base = "http://crashspacela.com/sign/";
my $id = "BigButton";
my $msg = "Someone+at+the+space!";
my $update_url;

my $diff_mins_max_default = 60;
my $diff_mins_max = $diff_mins_max_default;

my $lifetime_secs = (5 * 60) - 10;  # 10 secs short of 5 mins
my $max_trigger_secs = 60;     # how long between registered

my $verbose = 0;
my $portname;
my $poll_secs = 0.2;

my $click_count;
my $last_triggertime;
my $last_polltime;
my $start_time;

#
sub build_update_url($) {
    my ($type) = @_;
    my $mins_max = $diff_mins_max;
    if( $type eq 'cancel' ) { 
        $mins_max = 0;  # FIXME: hack!
    }
    $update_url = $update_url_base;
    $update_url .= "?id=$id&msg=$msg&diff_mins_max=$mins_max"; 
    $update_url .= "&type=$type";
    $update_url .= "&debug=1" if($verbose);
    
    print "update_url:$update_url\n" if($verbose>1);
}

#
sub do_update($$) {
    my ($t,$type) = @_;
    print "$t:$type: YAY!\n" if($verbose);
    build_update_url($type);
    my $response = get($update_url);  # update the sign

    $click_count = 0;
    $last_triggertime = $t;
}

#
sub serial_open($) {
    my ($portname) = @_;
    my $ob = Device::SerialPort->new($portname) 
        or die "Can't Open $portname: $!";
    $ob->baudrate(19200)   or die "failed setting baudrate";
    $ob->parity("none")    or die "failed setting parity";
    $ob->databits(8)       or die "failed setting databits";
    $ob->handshake("none") or die "failed setting handshake";
    $ob->read_const_time(200) or die "failed setting read timeout";
    $ob->read_char_time(20) or die "failed setting read timeout"; 
    $ob->write_settings    or die "no settings";
    return $ob;
}

#----------------------------------------------------------------------------
#
#

# get options for running program
my $help = 0;
my $rc = GetOptions( 'port|p=s'          => \$portname,
                     'm|mins=i'          => \$diff_mins_max,
                     'l|lifetime=i'      => \$lifetime_secs,
                     'help'              => \$help,
                     'v|verbose+'        => \$verbose,
                     'url=s',            => \$update_url_base,
                     );

if( !defined $portname ) {
    die "Error: must supply a serial port with -p <portname>!\n";
}

my $port = serial_open( $portname );

$start_time = time();
$last_polltime = time();
$last_triggertime = 0;
my $t = time();

print "$t: bigButtonDaemon starting up\n" if($verbose);
while( (time() - $start_time) < $lifetime_secs ) { 
    if( (time() - $last_polltime) > $poll_secs ) {
        $port->write("s$diff_mins_max\n");
        $last_polltime = time();
    }

    my $result = $port->lookfor();
    $t = time();
    if( $result ) {
        print "button: $result\n" if($verbose>1);
        if( $result =~ /triggered/ ) {
            # if duration between triggers is shorter than our max
            if( ($t - $last_triggertime)  < $max_trigger_secs ) {
                $click_count++;
                if( $click_count > 2 ) {
                    print "$t: multi-click CANCEL\n";
                    $port->write("s0\n");  # send cancel
                    do_update($t,"cancel");
                } 
                print "$t: Fast button pressing detected\n" if($verbose);
            } else { # else do an update
                do_update($t,"update");
            }
        }
    }
}
$t = time();
print "$t: bigButtonDaemon exiting normally\n" if($verbose);








